package com.ytjj.qmyx.mall.controller;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayOpenAuthTokenAppModel;
import com.alipay.api.domain.AppTokenExchangeSubElement;
import com.alipay.api.request.AlipayOpenAuthTokenAppRequest;
import com.alipay.api.response.AlipayMerchantOrderSyncResponse;
import com.alipay.api.response.AlipayOpenAuthTokenAppResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.ytjj.common.api.CommonResult;
import com.ytjj.common.constants.AlipayCertConstants;
import com.ytjj.common.constants.AlipayConstants;
import com.ytjj.common.controller.BaseController;
import com.ytjj.common.exception.ApiException;
import com.ytjj.common.model.UsersResponse;
import com.ytjj.common.model.request.AliPayOrderSyncRequest;
import com.ytjj.common.service.RedisService;
import com.ytjj.common.utils.AlipayUtil;
import com.ytjj.common.utils.TokenUtil;
import com.ytjj.qmyx.mall.client.FreightTemplateClient;
import com.ytjj.qmyx.mall.constants.RedisConstants;
import com.ytjj.qmyx.mall.mapper.OrdersInfoMapper;
import com.ytjj.qmyx.mall.mapper.OrdersMapper;
import com.ytjj.qmyx.mall.model.*;
import com.ytjj.qmyx.mall.model.request.AlipayOrderRequest;
import com.ytjj.qmyx.mall.service.AliPayComplaintsService;
import com.ytjj.qmyx.mall.service.AlipayService;
import com.ytjj.qmyx.mall.service.OrdersService;
import com.ytjj.qmyx.users.client.UsersClient;
import com.ytjj.qmyx.users.model.DefaultAddressDto;
import com.ytjj.qmyx.users.model.UsersDto;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * @Description 阿里云支付
 *
 * @Version 1.0
 * 
 */

@RefreshScope
@RestController
@RequestMapping("/alipay")
@Slf4j
public class AlipayController extends BaseController {
    @Resource
    private AlipayService alipayService;
    @Resource
    private OrdersMapper ordersMapper;
    @Resource
    private OrdersInfoMapper ordersInfoMapper;
    @Resource
    private OrdersService ordersService;
    @Autowired
    private UsersClient usersClient;
    @Resource
    private AlipayConstants alipayConstants;
    @Resource
    private AlipayCertConstants alipayCertConstants;
    @Resource
    private com.ytjj.common.service.AlipayService alipay;
    @Autowired
    private RedisService redisService;
    @Autowired
    private FreightTemplateClient freightTemplateClient;
    @Resource
    private AliPayComplaintsService aliPayComplaintsService;

    @Value("${order.blackAddress:公安局,派出所,检察院,法院,工商局}")
    private String blackAddress;

    @Value("${create.order.filter.switch:1}")
    private Integer createOrderFilterSiwtch;

    @Value("${h5token.blacks:3f1c2a35-f4f4-7ea4-d0da-8f8c7db261a2,c6b7d2c7-2e32-82f7-747a-cab1596846b6}")
    private String h5TokenBlackList;
    /**
     * 支付宝 app预支付
     *
     * @param request
     * @return
     */
    @PostMapping("/appPayOrder")
    public CommonResult appPayOrder(@RequestBody AlipayOrderRequest request) {
        log.info("======appPayOrder=========");
//        if (request.getAddressId() == null) {
//            return CommonResult.failed("收货地址未填写");
//        }
        UsersResponse usersResponse = this.getCurrentUser();

        DefaultAddressDto oneAddress = usersClient.getAddressByUserIdOrId(usersResponse.getId(), request.getAddressId());
        if (oneAddress == null || StringUtils.isBlank(oneAddress.getCity())) {
            Orders orders = ordersMapper.selectByPrimaryKey(request.getOrderId());
            oneAddress = new DefaultAddressDto();
            oneAddress.setProvince(orders.getProvince());
            oneAddress.setCity(orders.getCity());
            oneAddress.setArea(orders.getArea());
            oneAddress.setAddress(orders.getAddress());
            oneAddress.setTel(orders.getUserPhone());
            oneAddress.setName(orders.getUserName());
        }
        String city = oneAddress.getCity();
        if (city!=null && city.equals("市辖区")){
            city = oneAddress.getProvince();
        }
        String province = oneAddress.getProvince();

        //敏感地址限制
        if (org.apache.commons.lang3.StringUtils.isNotBlank(oneAddress.getAddress()) && blackAddress!=null){
            String[] blackAddressList = blackAddress.split(",");
            for (String bd : blackAddressList) {
                if (oneAddress.getAddress().contains(bd)){
                    throw new ApiException("该地区不可下单,-3");
                }
            }
        }
        //校验商品上下架/库存/收货地址
        if (null != request.getOrderId()) {
//            Orders orders = ordersMapper.selectByPrimaryKey(request.getOrderId());
            OrdersInfoExample ordersInfoExample = new OrdersInfoExample();
            ordersInfoExample.createCriteria().andOrderIdEqualTo(request.getOrderId());
            List<OrdersInfo> ordersInfoList = ordersInfoMapper.selectByExample(ordersInfoExample);
            String finalCity = city;
            log.info("==========finalCity========{}",finalCity);
            ordersInfoList.stream().forEach(ordersInfo -> {
                boolean b = ordersService.checkProductStock(ordersInfo.getProductId(), ordersInfo.getProductSpecId(), ordersInfo.getProductSum());
                if (!b) {
                    throw new ApiException("库存不足，请稍后再来");
                }
                //获取运费模板
                FreightTemplateResponse freightTemplateResponse = ordersService.getFreightTemplateResponse(ordersInfo.getProductId());
                if (null != freightTemplateResponse) {
                    log.info("==========freightTemplateResponse========{}",freightTemplateResponse);
                    //判断是否在限制地区
                    YxAstrictRegionResponse astrictRegion = freightTemplateResponse.getAstrictRegion();
                    if (ObjectUtil.isNotNull(astrictRegion) && org.apache.commons.lang3.StringUtils.isNotBlank(astrictRegion.getRegionDesc())) {
                        String[] region = astrictRegion.getRegionDesc().split(",");
                        Optional<String> regionFlag = Stream.of(region).filter(x -> x.contains(province)).findFirst();
                        if (regionFlag.isPresent() && regionFlag.get().contains("全境")) {
                            throw new ApiException("您所在的区域该商品不能下单，先去看看其他商品吧~");
                        }
                    }

                    if (null != astrictRegion && StringUtils.isNotBlank(astrictRegion.getRegion())) {
                        String[] region = astrictRegion.getRegion().split(",");
                        Optional<String> regionFlag = Stream.of(region).filter(x -> x.equals(finalCity)).findFirst();
                        if (regionFlag.isPresent() && org.apache.commons.lang3.StringUtils.isNotBlank(regionFlag.get())) {
                            throw new ApiException("您所在的区域该商品不能下单，先去看看其他商品吧~");
                        }
                    }
                }
//                CommonResult<FreightTemplateResponse> freightTemplateResponse = freightTemplateClient.selectYxFreightTemplateByProductId(ordersInfo.getProductId());
//                CommonResult<FreightTemplateResponse> chainFreightTemplateResponse = freightTemplateClient.selectChainFreightTemplateByProductId(ordersInfo.getProductId());
//                if(freightTemplateResponse != null || chainFreightTemplateResponse !=null ) {
//                    Boolean judgeResult = alipayService.judgeRegionList(freightTemplateResponse.getData(), chainFreightTemplateResponse.getData(), oneAddress.getCity());
//                    if(!judgeResult) {
//                        throw new ApiException("该地区不可下单,请更改默认地址");
//                    }
//                }
            });
        }

        UsersDto usersDto = usersClient.getUsersInfo(usersResponse.getId());
        request.setScore(usersDto.getScore());
        request.setSourcePlatform(usersResponse.getSource());
        request.setAlipayUserId(usersDto.getAlipayUserId());
        request.setChildId(getChildId());
        ordersService.checkPaymentChannelStatus("aliPay");
        return CommonResult.success(alipayService.appPayOrder(request));
    }

    /**
     * 支付宝小程序回调
     *
     * @param params
     * @return
     */
    @RequestMapping("/receiveAppMessage/{tradeType}/{childId}")
    public String receiveJsApiMessage(HttpServletRequest params,@PathVariable String tradeType,@PathVariable String childId) {
        log.info("======receiveAppMessage=========tradeType:{},childId:{}",tradeType,childId);
        String callback = alipayService.callback(params,tradeType,childId);
        return callback;
    }

    /**
     * 支付宝投诉回调
     * @param request
     * @param childId
     * @return
     * @throws Exception
     */
    @RequestMapping("/callBack/{childId}")
    public String aliPayCallBack(HttpServletRequest request,@PathVariable String childId) throws Exception {
        Map<String, String> params = AlipayUtil.convertRequestParamsToMap(request);
        log.info("支付宝回调参数params:{},childId:{}", JSON.toJSONString(params),childId);
        if ("alipay.merchant.tradecomplain.changed".equals(params.get("msg_method"))) {
            return aliPayComplaintsService.complaintsCallBack(params,childId);
        }
        return  "success";
    }


//    /**
//     * app 支付回调
//     *
//     * @param params
//     * @return
//     */
//    @RequestMapping("/receiveAppPayResultMessage")
//    public String receiveAppMessage(HttpServletRequest params) {
//        log.info("======receiveAppPayResultMessage=========");
//        String callback = alipayService.callback(params,null,null);
//        return callback;
//    }


    ////////////////////////////////////////////////////////////////////////


    /**
     * 支付宝 快应用预支付
     *
     * @param request
     * @return
     */
    @PostMapping("/quickAppPay")
    public CommonResult quickAppPay(@RequestBody AlipayOrderRequest request) {
        log.info("======quickAppPay=========");
        return CommonResult.success(alipayService.quickAppPay(request));
    }


    ////////////////////////////////////////////////////////////////////////

    /**
     * 手机H5支付
     *
     * @param payRequest
     * @return
     */
    @PostMapping("/h5Pay")
    public CommonResult mobilePay(@RequestBody AlipayOrderRequest payRequest, HttpServletResponse response) {
        log.info("======mobilePay========={}", payRequest);
        String h5_token = TokenUtil.getToken();
        String domainUrl = TokenUtil.getDomainUrl();
        if (1 == createOrderFilterSiwtch && !org.springframework.util.StringUtils.isEmpty(h5TokenBlackList)) {
            log.info("====h5_token==={}", h5_token);
            String[] h5TokenBlackLists = h5TokenBlackList.split(",");
            List<String> h5Tokens = Arrays.asList(h5TokenBlackLists);
            if (h5Tokens.contains(h5_token)) {
                log.info("===h5 token is enter black list==={}", h5_token);
                throw new ApiException("-1005");
            }
        }
        ordersService.checkPaymentChannelStatus("aliPay",domainUrl);
        return CommonResult.success(alipayService.h5PayOrder(payRequest, response, getH5CurrentUser()));
    }

    /**
     * 获取 app_auth_code(支付宝回调接口)
     *
     * @param app_id        开发者appId
     * @param app_auth_code 当次授权的授权码
     */
    @GetMapping("/appAuthCodeCallback")
    public String appAuthCodeCallback(@RequestParam("app_id") String app_id, @RequestParam("app_auth_code") String app_auth_code) {
        log.info("===app_auth_code callback===={}, {}", app_id, app_auth_code);
        if (alipayCertConstants.getAPPID().equals(app_id)) {
            redisService.set(RedisConstants.APPAUTHCODE_KEY + app_id, app_auth_code);
            try {
                appAuthTokenByAppId(app_id, null);
            } catch (AlipayApiException e) {
                e.printStackTrace();
            }
            return "true";
        }
        return "failure";
    }

    /**
     * 根据app_auth_code 换取 app_auth_token
     *
     * @return
     */
//    @GetMapping("/appAuthTokenByAppId")
    private CommonResult appAuthTokenByAppId(@RequestParam("appId") String appId, @RequestParam("refreshToken") String refreshToken) throws AlipayApiException {
        String appAuthCode = redisService.get(RedisConstants.APPAUTHCODE_KEY + appId);
        if (StringUtils.isEmpty(appAuthCode)) {
            log.info("===获取appAuthCode失败==={}", appId);
            throw new ApiException("获取AppAuthCode失败");
        }

        CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
        certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");  //gateway:支付宝网关（固定）https://openapi.alipay.com/gateway.do
        certAlipayRequest.setAppId(alipayCertConstants.getAPPID());  //APPID 即创建应用后生成,详情见创建应用并获取 APPID
        certAlipayRequest.setPrivateKey(alipayCertConstants.getRSA_PRIVATE_KEY());  //开发者应用私钥，由开发者自己生成
        certAlipayRequest.setFormat("json");  //参数返回格式，只支持 json 格式
        certAlipayRequest.setCharset("UTF8");  //请求和签名使用的字符编码格式，支持 GBK和 UTF-8
        certAlipayRequest.setSignType(alipayConstants.getSIGNTYPE());  //商户生成签名字符串所使用的签名算法类型，目前支持 RSA2 和 RSA，推荐商家使用 RSA2。
        certAlipayRequest.setCertPath(alipayCertConstants.getAPP_CERT_PATH()); //应用公钥证书路径（app_cert_path 文件绝对路径）
        certAlipayRequest.setAlipayPublicCertPath(alipayCertConstants.getALIPAY_CERT_PATH()); //支付宝公钥证书文件路径（alipay_cert_path 文件绝对路径）
        certAlipayRequest.setRootCertPath(alipayCertConstants.getALIPAY_ROOT_CERT_PATH());  //支付宝CA根证书文件路径（alipay_root_cert_path 文件绝对路径）
        AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);

        log.info("===alipay constants==={},{}", alipayConstants.getSIGNTYPE(), alipayCertConstants.getAPP_CERT_PATH());
        AlipayOpenAuthTokenAppRequest request = new AlipayOpenAuthTokenAppRequest();
        AlipayOpenAuthTokenAppModel model = new AlipayOpenAuthTokenAppModel();
        model.setGrantType("authorization_code");//换码类型 authorization_code：使用 auth_code 换取令牌；refresh_token：使用刷新刷新令牌
        model.setCode(appAuthCode);//授权码 grant_type= authorization_code 时，必须录入
//        model.setRefreshToken(refreshToken);//刷新令牌
        request.setBizModel(model);
        try {
            AlipayOpenAuthTokenAppResponse response = alipayClient.certificateExecute(request);
            log.info("===appAuthTokenByAppId response==={}", JSONObject.toJSONString(response));
            String code = response.getCode();
            if (!"10000".equals(code)) {
                return CommonResult.failed();
            }
            List<AppTokenExchangeSubElement> tokens = response.getTokens();
            String appAuthToken_response = tokens.get(0).getAppAuthToken();
            String refreshToken_response = tokens.get(0).getAppRefreshToken();
            redisService.set(RedisConstants.APPAUTHTOKEN_KEY + appId, appAuthToken_response);
            redisService.expire(RedisConstants.APPAUTHTOKEN_KEY + appId, 364 * 24 * 60 * 60);
            redisService.set(RedisConstants.APPREFRESHTOKEN_KEY + appId, refreshToken_response);
            return CommonResult.success();
        } catch (Exception e) {
            log.info("==={}===", e);
        }
        return CommonResult.failed();
    }


    /**
     * 支付宝 H5支付 回调
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/receiveH5Message")
    public String receiveH5Message(HttpServletRequest request, HttpServletResponse response) throws Exception {
        log.info("======receiveH5Message=========");
        return alipayService.h5CallBack(request, response);
    }

    @GetMapping("/getAlipayRes")
    public AlipayTradeQueryResponse getAlipayRes(String outTradeNo, String tradeNo) {
        try {
            return alipay.AliPayAppOrderQuery("G202102280831050137251", "2021022822001476271447108653");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @PostMapping("/syncAliPayOrder")
    public AlipayMerchantOrderSyncResponse syncAliPayOrder(@RequestBody AliPayOrderSyncRequest request) throws Exception {
        return alipayService.syncAliPayOrder(request.getOrderStatus(), request.getOrderNo(),request.getOrderId(),request.getUserId(),
                request.getProductName(),request.getCreateTime(),request.getChildId(),request.getProductImg());
    }

    /**
     * 获取最新切换的域名
     * @return
     */
//    @GetMapping("/getZfbNewUrl")
//    public CommonResult getZfbNewUrl(){
//        return CommonResult.success(redisService.get("zfbNewUrl"));
//    }
}
